/*
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <darktempler@gmail.com> wrote this file. As long as you retain this notice you
 * can do whatever you want with my code. If we meet some day, and you think
 * this code is worth it, you can buy me a beer in return - Matt Labrum (-dt-)
 * ----------------------------------------------------------------------------
 */
 
 /* 
	$LastChangedBy: dt $
	$LastChangedDate: 2007-08-18 01:56:27 -0700 (Sat, 18 Aug 2007) $
	$LastChangedRevision: 311 $
	$HeadURL: http://version.thedt.net/scripts/plusscripts/musicNowplaying/prefstore.js $
*/
 
 
 /*
 Basic use
 
 var Prefs = new PrefStore("xxx");
 
 Prefs.set("moo","cow");
 
 Debug.Trace(Prefs.get("moo"));
 
 you can store them in levels aswell like
 
 Prefs.set("moo/goes/the/cow","test");
 
 Debug.Trace(Prefs.get("moo/goes/the/cow));
 
 also you can store more than just text, you can store arrays , boolean values and numbers.
 
 */

var PrefStore = function(filename){
	this.file =  new ActiveXObject("Scripting.FileSystemObject");
			
	this.filename = MsgPlus.ScriptFilesPath + '/' + filename + '.xml';
	this.xml = new ActiveXObject("Microsoft.XMLDOM");
	this.xml.async=false;
	this.xml.preserveWhiteSpace = true;
					
	if(!this.file.FileExists(this.filename)){
		this.createFile();
	}else{
		this.loadXML();
	}
					
	this.encoder = new serializer();
	this.decoder = new unserializer();
}

PrefStore.prototype = {
	"FirstTime" : false,
	"createFile" : function(){
		this.FirstTime = true;
		var topNode = this.xml.createElement('prefs');
		this.xml.appendChild(topNode);
		this.save();	
	},
	
	"loadXML" : function(){
		this.xml.load(this.filename);
	},
	
	"save" : function(){
		this.xml.save(this.filename);
	},
	
	"remove" : function(path){
		var xpath = 'prefs/' + this.pathToXpath(path);
		var node = this.xml.selectNodes(xpath);
		if(node.length > 0){
			node[0].parentNode.removeChild(node[0]);
		}else{
			Debug.Trace("unable to remove path" + path);
		}
	},
	
	
	"set" : function(path,data){
		//path = String(path).toLowerCase( );
		path = path.split('/');
		



		var lastNode = this.xml.getElementsByTagName('prefs')[0];

		for(var i=0;i<path.length;i++){
			
			var node = lastNode.selectNodes('pref[@name="'+path[i]+'"]');
			if(node.length != 0){
				lastNode = node[0];
				lastNode.setAttribute('s',"1");
			}else{
				var node = this.xml.createElement('pref');
				node.setAttribute('name',path[i]);
				node.setAttribute('s',"1");
				lastNode.appendChild(node);
				lastNode = node;
			}
			
		}
		
		
		var text = this.xml.createTextNode(this.encoder.parse(data));
		var textNodeF = this.getFirstTextNode(lastNode);
		if(textNodeF){
			lastNode.replaceChild(text,textNodeF);
		}else{
			lastNode.appendChild(text);
		}
		
	
	},
	
	"get" : function(path){
		
		var xpath = 'prefs/' + this.pathToXpath(path);
		
	
		var element = this.xml.selectNodes(xpath);
		
		if(element.length != 0){
			var text = this.getFirstTextNode(element[0]);
			if(text){
				if(element[0].getAttribute('s')){
					return this.decoder.parse(text.text);
				}else{
					return text.text;
				}
			}
		
		}
		return -1;

	},
	
	"getAsArray" : function(path){
		var xpath = 'prefs/' + this.pathToXpath(path) + '/*';
		
		var returns = {};
		
		var elements =  this.xml.selectNodes(xpath);

		if(elements.length==0){
			Debug.Trace('fat zero');
			return returns;
		}
		
		var array = {};
		for(var i=0;i<elements.length;i++){
			if(elements[i].nodeType == 1)
				array = this.getAsArrayAddNode(elements[i],array);
		}
		return array;
	},
	
	"getAsArrayAddNode" : function(node,array){
	
		if(node.childNodes.length==1){
			array[node.getAttribute("name")] = (node.getAttribute('s') == 1) ? this.decoder.parse(this.getFirstTextNode(node).text) : this.getFirstTextNode(node).text;
		}else if(node.childNodes.length==0){
			array[node.getAttribute("name")] = '';
		}else{
			//more than one child...
			array[node.getAttribute("name")] = {};
			
			for(var i=0;i<node.childNodes.length;i++){
				if(node.childNodes[i].nodeType == 1)
					array[node.getAttribute("name")] = this.getAsArrayAddNode(node.childNodes[i],array[node.getAttribute("name")]);
			}
		}
	
		return array;
	},
	
	"pathToXpath" : function(path){
		var parts = path.split('/');
		var xpath = '';
		for(var i=0;i<parts.length;i++){
			xpath += "pref[@name='"+parts[i]+"']/";
		}
		
		return xpath.substring(0,xpath.length-1);
	},
	
	"getFirstTextNode" : function(element){
		if(element.hasChildNodes){
			for(var i=0;i<element.childNodes.length;i++){
				if(element.childNodes[i].nodeType == 3){
					return element.childNodes[i];
				}
			}
		}

		return false;
	}


}


 //acts like the php function http://php.net/unserialize
var unserializer = function(){};

unserializer.prototype = {

	"parse" : function(raw){
		var type = raw.substr(0,1);
		
		switch(type){
			case "s" : return this.string(raw);
			case "i" : return this.int(raw);
			case "b" : return this.bool(raw);
			case "a" : return this.array(raw);
		}
		
	},
	
	"string" : function(raw){
		var match = raw.match(/^s:([0-9]+):"(.*)";/);
		return match[2];
	},
	
	"array" : function(raw){

		var match = raw.match(/^a:[0-9]+:{(.*)}$/);
		var chrs = match[1].split("");
		if(chrs.length == 0)return new Array();
		
		//couldnt think of a regexp way to do this >< 
		var keys = new Array("");
		var inString = false;
		var inArray = false;
		var x = 0;
		for(var i=0;i<chrs.length;i++){		
			if(chrs[i] == "{" && !inArray && !inString){
				inArray = true;
			}else if(chrs[i] == "}" && inArray && !inString){
				inArray = false;		
				var next = match[1].substr(i+1,1);
				if(next == "s" || next == "i" || next == "b" || next == "a"){
					keys[x] += chrs[i];
					x++;
					keys[x] = "";
					continue;
				}		
			}else if(chrs[i] == ";" && !inString && i != chrs.length-1 && !inArray){
				keys[x] += chrs[i];
				x++;
				keys[x] = "";
				continue;
			}else if(chrs[i] == '"'){
				if(match[1].substr(i+1,1) == ";"){
					inString = false;
				}else{
					inString = true;
					
				}
			}
			keys[x] += chrs[i];
		}

		var returnA = new Array(); //naughty dt you're adding named keys to an array :O
		

		for(i=0;i<keys.length;i=i+2){
			
			returnA[this.parse(keys[i])] = this.parse(keys[i+1]);
		}
	
		if((typeof (returnA[0]) == "undefined") & returnA.length !=0 ) returnA.splice(0,1);

		
		return returnA;
	},
	
	"bool" : function(raw){
		var match = raw.match(/^b:([0-1]);/);
		return (match[1] == 0) ? false : true;
	},
	
	"int" : function(raw){
		var match = raw.match(/^i:([0-9.]+);/);
		if(match[1].match(".")){
			return parseFloat(match[1]);
		}else{
			return parseInt(match[1])
		}
	}
}




//acts like the php function http://php.net/serialize
var serializer = function(){};
serializer.prototype = {
	"parse" : function(thing){
		return this.type(thing);
	},

	"type" : function(thing){
		switch(typeof(thing)){
			case "number" : return this.number(thing);
			case "string" : return this.string(thing);
			case "boolean" : return this.bool(thing);
		}
		
		if(typeof(thing) == 'object'){
			try{
				var name = String(thing.constructor).match(/function (.*)\(\)/)[1]
				
				switch(name){
					case 'Array' : return this.array(thing);
					case 'Object' : return this.object(thing);
				}
			}catch(e){}

		}
		return '';
	},

	"number" : function(num){
		return 'i:' + num + ';';
	},
	
	"string" : function(str){
		return "s:" + str.length + ':"' + str +  '"'+';';
	},
	
	"array" : function(array,num){
		
		if(typeof(num) == 'undefined'){
			var str = 'a:' + array.length + ':{'
		}else{
			var str = 'a:' + num + ':{'
		}
		
			var items = [];
			for(var i=0;i<array.length;i++){
				if(typeof(num)=='undefined'){
					items[items.length] = this.number(i) + this.type(array[i]);
				}else{
					items[items.length] = this.type(array[i]);
				}
			}
		
			str += items.join('');
		
		return str + '}'
	},
	
	"object" : function(obj){
		
		var names = 0;
		var items = Array();
		for(x in obj){
			items[items.length] = x;
			items[items.length] = obj[x];
			names++;
		}
		return this.array(items,names);
	},
	
	"bool" : function(thing){
		return "b:" + ((thing) ? "1" : "0") + ";";
	}

}